#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ISO8583.h>
#include <Prot8583.h>
#include <aclutil.h>
#include <svc.h>
#include <aclstr.h>

//#include "C:\Verixaps\VMAC\include\logsys.h"
//#include "C:\VerixVaps\VMAC\ver150\include\logsys.h"
#include <logsys.h>


#include "UserIf.h"
#include "Msg.h"


#define VARIABLE(name) (void *)name,sizeof(name)
#define TABLE(name) (void *)name, 0
#define FUNCTION(name) (void *)name, 0
#define XXXX 1000

Message_Struct ISOMess;
unsigned char source[101];
unsigned char dest[101];

TRANSACTION_BITMAP obTranMapCurr;

extern char Iklan[1000];
extern TRANSACTION_BITMAP obTranMap[];
extern int obTranMapCount;

converters convert_table[] = {
	{asc_to_asc, asc_to_asc},
	{av3_to_av3, av3_to_av3},
	{bit_to_bit, bit_to_bit},
	{bcd_to_bcd, bcd_to_bcd},
	{asc_to_bcd, bcd_to_asc},
	{str_to_asc, asc_to_str},
	{str_to_bcd, bcd_to_str},
	{str_to_bcd, bcd_to_snz},
	{str_to_av2, av2_to_str},
	{str_to_bv2, bv2_to_str},
	{str_to_av3, av3_to_str},
	{str_to_xbc, xbc_to_str},
	{hst_to_bin, bin_to_hst},
	{hst_to_bi2, bi2_to_hst},
	{hst_to_bi3, bi3_to_hst},
};

variant_struct VariantField_60[] = {  //defined in iso8583.h
	//{0x00, 0x0220, 12, BCD_STR, VARIABLE(ISOMess.field_60)},
	{0x40, 0x0100, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PreTransfer Req
	{0x40, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PreTRansfer Resp	
	{0x40, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Transfer Req
	{0x40, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //TRansfer Resp	
	{0x40, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //TRansfer Reversal	
	{0x50, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay CC Req
	{0x50, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay CC Resp
	{0x50, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay CC Req Reversal	
	{0x60, 0x0100, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PrePay PLN
	{0x60, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PrePay PLN Resp	
	{0x60, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay PLN
	{0x60, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay PLN Resp	
	{0x60, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay PLN Reversal
	{0x70, 0x0100, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PrePay Telpon
	{0x70, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //PrePay Telpon Resp	
	{0x70, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay Telpon
	{0x70, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay Telpon Resp	
	{0x70, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay Telpon Reversal
	{0x80, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay HP Req
	{0x80, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay HP Resp	
	{0x80, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Pay HP Req Reversal
	{0x90, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Topup HP Req
	{0x90, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Topup HP Resp
	{0x90, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Topup HP Req Reversal
	{0x10, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Voucher HP Req & Debet Point
	{0x10, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Voucher HP Resp & Debet
	{0x10, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Voucher HP Req Reversal & Debet
	{0x10, 0x0300, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Reg Mobile Banking
	{0x00, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Credit Point Req
	{0x00, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Credit Point Resp
	{0x00, 0x0400, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Credit Point Req Reversal
	{0x00, 0x0220, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Offline Credit Point Req
	{0x00, 0x0230, 99, AV3_STR, VARIABLE(ISOMess.field_60)},  //Offline Credit Point Resp
	{0x03, 0x0200, 99, AV3_STR, VARIABLE(ISOMess.field_60)},
	{0x90, 0x0810, 99, AV3_STR, VARIABLE(ISOMess.field_60)},
	{0x92+STOP, 0x0500, 6, BCD_STR, VARIABLE(ISOMess.field_60)},
};

variant_struct VariantField_63[] = {  //defined in iso8583.h
	{0x00, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Purchase
	{0x50, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Isi Ulang, PAYMENT
	{0x80, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Registration
	
	{0x31, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Saldo
	{0x38, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Mini Statement
	{0x39, 0x0310, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Credit Card
	{0x38, 0x0310, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Billing
	{0x40, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata TRF 2 CIF
	{0x49, 0x0210, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata TRF 2 Other Banks

	{0x00, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Purchase
	{0x50, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Isi Ulang, PAYMENT
	{0x80, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Registration
	
	{0x31, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Saldo
	{0x38, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Mini Statement
	{0x39, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Credit Card
	{0x38, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata Info Billing
	{0x40, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata TRF 2 CIF
	{0x49, 0x0110, 99, AV3_STR, VARIABLE(ISOMess.field_63)},  //Permata TRF 2 Other Banks


	{0x80, 0x0800, 18, BCD_BCD, VARIABLE(ISOMess.field_63)},
	{0x92+STOP, 0x0500, 6, BCD_STR, VARIABLE(ISOMess.field_63)},
};

unsigned int return_variant1()
{
	char buff[3];
	memset(buff, 0x00, sizeof(buff));
	strncpy(buff, (const char *)ISOMess.field_03, 2); //most sign. 2 digits of proc_code
	return (strtol(buff, NULL, 16));
}

unsigned int return_variant2()
{
	return (strtol((char *)ISOMess.message_id, NULL, 16));
}

/*
int compute_field(int how, unsigned char *buffer, int *psz, int *vsz)
{
	*psz = 19;  //value from second column of field_table, see below
	*vsz = sizeof(ISOMess.field_02); //This Function just as example
	if (how==0) {
		src_8583 = (unsigned char *) ISOMess.field_02;
	}else {
		dst_8583 = (unsigned char *) ISOMess.field_02;
	}
	return (BV2_STR);
}
*/
field_struct field_table[] = {  //defined in ISO8583.h
	{0,			10, BCD_STR, VARIABLE(ISOMess.tpdu) },
	{0,			 4,	BCD_STR, VARIABLE(ISOMess.message_id)},
	{2,			19, BV2_STR, VARIABLE(ISOMess.field_02)},
	{3,			 6, BCD_STR, VARIABLE(ISOMess.field_03)},
	{4,			12, BCD_SNZ, VARIABLE(ISOMess.field_04)},
	{5+SKIP,	12, BCD_STR, VARIABLE(ISOMess.discard)},
	{6+SKIP,	12, BCD_STR, VARIABLE(ISOMess.discard)},
	{7+SKIP,	10, BCD_STR, VARIABLE(ISOMess.discard)},
	{8+SKIP,	 8, BCD_STR, VARIABLE(ISOMess.discard)},
	{9+SKIP,	 8, BCD_STR, VARIABLE(ISOMess.discard)},
	{10+SKIP,	 8, BCD_STR, VARIABLE(ISOMess.discard)},
	{11,		 6, BCD_STR, VARIABLE(ISOMess.field_11)},
	{12,		 6, BCD_STR, VARIABLE(ISOMess.field_12)},
	{13,		 4, BCD_STR, VARIABLE(ISOMess.field_13)},
	{14,		 4, BCD_STR, VARIABLE(ISOMess.field_14)},
	{15+SKIP,	 4, BCD_STR, VARIABLE(ISOMess.discard)},
	{16+SKIP,	 4, BCD_STR, VARIABLE(ISOMess.discard)},
	{17+SKIP,	 4, BCD_STR, VARIABLE(ISOMess.discard)},
	{18+SKIP,	 4, BCD_STR, VARIABLE(ISOMess.discard)},
	{19+SKIP,	 3, BCD_STR, VARIABLE(ISOMess.discard)},
	{20+SKIP,	 3, BCD_STR, VARIABLE(ISOMess.discard)},
	{21+SKIP,	 3, BCD_STR, VARIABLE(ISOMess.discard)},
	{22,		 3, BCD_STR, VARIABLE(ISOMess.field_22)},
	{23+SKIP,	 3, BCD_STR, VARIABLE(ISOMess.discard)},
	{24,		 3, BCD_STR, VARIABLE(ISOMess.field_24)},
	{25,		 2, BCD_STR, VARIABLE(ISOMess.field_25)},
	{26+SKIP,	 2, BCD_STR, VARIABLE(ISOMess.discard)},
	{27+SKIP,	 1, BCD_STR, VARIABLE(ISOMess.discard)},
	{28,		 8, XBC_STR, VARIABLE(ISOMess.field_28)},
	{29+SKIP,	 8, XBC_STR, VARIABLE(ISOMess.discard)},
	{30+SKIP,	 8, XBC_STR, VARIABLE(ISOMess.discard)},
	{31+SKIP,	 8, XBC_STR, VARIABLE(ISOMess.discard)},
	{32,		11, BV2_STR, VARIABLE(ISOMess.field_32)},
	{33+SKIP,   11, BV2_STR, VARIABLE(ISOMess.discard)},
	{34+SKIP,   28, AV2_STR, VARIABLE(ISOMess.discard)},
	{35,		37, BV2_STR, VARIABLE(ISOMess.field_35)},
	{36+SKIP,  104, AV2_STR, VARIABLE(ISOMess.discard)},
	{37,		12, ASC_STR, VARIABLE(ISOMess.field_37)},
	{38,         6, ASC_STR, VARIABLE(ISOMess.field_38)},
	{39,		 2, ASC_STR, VARIABLE(ISOMess.field_39)},
	{40+SKIP,    3, ASC_STR, VARIABLE(ISOMess.discard)},
	{41,		 8, ASC_STR, VARIABLE(ISOMess.field_41)},
	{42,		15, ASC_STR, VARIABLE(ISOMess.field_42)},
	{43,		40, ASC_STR, VARIABLE(ISOMess.field_43)},
	{44,		25, AV2_STR, VARIABLE(ISOMess.field_44)},
	{45+SKIP,   76, AV2_STR, VARIABLE(ISOMess.discard)},
	{46+SKIP,  999, AV3_STR, VARIABLE(ISOMess.discard)},
	{47+SKIP,  999, AV3_STR, VARIABLE(ISOMess.discard)},
	{48		,  999, AV3_STR, VARIABLE(ISOMess.field_48)},
	{49+SKIP,    3, ASC_STR, VARIABLE(ISOMess.discard)},
	{50+SKIP,    3, ASC_STR, VARIABLE(ISOMess.discard)},
	{51+SKIP,    3, ASC_STR, VARIABLE(ISOMess.discard)},
	{52,		64, BIT_BIT, VARIABLE(ISOMess.field_52)},
	{53+ SKIP,  16,  BCD_STR, VARIABLE(ISOMess.discard)},
	{54,	    99, AV3_STR, VARIABLE(ISOMess.field_54)},
	{55+ SKIP, 999, AV3_STR, VARIABLE(ISOMess.discard)},
	{56+ SKIP, 999, AV3_STR, VARIABLE(ISOMess.discard)},
	{57+ SKIP, 999, AV3_STR, VARIABLE(ISOMess.discard)},
	{58+ SKIP, 999, AV3_STR, VARIABLE(ISOMess.discard)},
	{59+ SKIP, 999, AV3_STR, VARIABLE(ISOMess.discard)},
	{60, 0, VARIANT, TABLE(VariantField_60)},  //60..63: private fields
	{61,        99, AV3_STR, VARIABLE(ISOMess.field_61)},  //utk iklan
	{62,	    10, AV3_STR, VARIABLE(ISOMess.field_62)},  //invoice Number
	{63, 0, VARIANT, TABLE(VariantField_63)},
	{64+ SKIP,  64, BIT_BIT, VARIABLE(ISOMess.discard)},
	{66+ SKIP,   1, BCD_STR, VARIABLE(ISOMess.discard)},
	{67+ SKIP,   2, BCD_STR, VARIABLE(ISOMess.discard)},
	{68+ SKIP,   3, BCD_STR, VARIABLE(ISOMess.discard)},
	{69+ SKIP,   3, BCD_STR, VARIABLE(ISOMess.discard)},
	{70+ SKIP,   3, BCD_STR, VARIABLE(ISOMess.discard)},
	{71,		 4, BCD_STR, VARIABLE(ISOMess.field_71)},
	{72,		 4, BCD_STR, VARIABLE(ISOMess.field_72)},
	{73+ SKIP,   6, BCD_STR, VARIABLE(ISOMess.discard)},
	{74+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{75+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{76+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{77+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{78+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{79+ SKIP,  10, BCD_STR, VARIABLE(ISOMess.discard)},
	{80,		10, BCD_STR, VARIABLE(ISOMess.field_80)},
	{81,		10, BCD_STR, VARIABLE(ISOMess.field_81)},
	{82+ SKIP,  12, BCD_STR, VARIABLE(ISOMess.discard)},
	{83+ SKIP,  12, BCD_STR, VARIABLE(ISOMess.discard)},
	{84+ SKIP,  12, BCD_STR, VARIABLE(ISOMess.discard)},
	{85+ SKIP,  12, BCD_STR, VARIABLE(ISOMess.discard)},
	{86+ SKIP,  16, BCD_STR, VARIABLE(ISOMess.discard)},
	{87+ SKIP,  16, BCD_STR, VARIABLE(ISOMess.discard)},
	{88+ SKIP,  16, BCD_STR, VARIABLE(ISOMess.discard)},
	{89+ SKIP,  16, BCD_STR, VARIABLE(ISOMess.discard)},
	{90+ SKIP,  42, BCD_STR, VARIABLE(ISOMess.discard)},
	{91+ SKIP,   1, ASC_STR, VARIABLE(ISOMess.discard)},
	{92+ SKIP,   2, ASC_STR, VARIABLE(ISOMess.discard)},
	{93+ SKIP,   5, ASC_STR, VARIABLE(ISOMess.discard)},
	{94+ SKIP,   7, ASC_STR, VARIABLE(ISOMess.discard)},
	{95+ SKIP,  42, ASC_STR, VARIABLE(ISOMess.discard)},
	{96+ SKIP,  64, BIT_BIT, VARIABLE(ISOMess.discard)},
	{97+ SKIP,  16, XBC_STR, VARIABLE(ISOMess.discard)},
	{98+ SKIP,  25, ASC_STR, VARIABLE(ISOMess.discard)},
	{99+ SKIP,  11, BV2_STR, VARIABLE(ISOMess.discard)},
	{100+ SKIP, 11, BV2_STR, VARIABLE(ISOMess.discard)},
	{101+ SKIP, 17, AV2_STR, VARIABLE(ISOMess.discard)},
	{102+ SKIP, 28, AV2_STR, VARIABLE(ISOMess.discard)},
	{103+ SKIP, 28, AV2_STR, VARIABLE(ISOMess.discard)},
	{104+ SKIP,100, AV3_STR, VARIABLE(ISOMess.discard)},
	{105+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{106+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{107+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{108+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{109+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{110+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{111+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{112+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{113+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{114+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{115+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{116+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{117+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{118+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{119+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{120+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{121+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{122+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{123+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{124+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{125+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{126+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{127+ SKIP,999, AV3_STR, VARIABLE(ISOMess.discard)},
	{128+ SKIP+ STOP,64, BIT_BIT, VARIABLE(ISOMess.discard)},
};

int SetBitmap(TRANSACTION_OBJECT *pobTran)
{
	int i;
	int nbyte;
	char buff[128];

	memset((char *)&ISOMess, 0x00, sizeof(ISOMess));
	memset((char *)&obTranMapCurr, 0x00, sizeof(obTranMapCurr));

	//Standard Bitmap
	for (i=0; i<obTranMapCount; i++) {
		if (pobTran->inCode == obTranMap[i].inCode) {
			if (pobTran->Status==0) { //Main Trx
				strcpy((char *)obTranMapCurr.bitmap, (char *)obTranMap[i].bitmap);
				{
					memset(buff, 0x00, sizeof(buff));
					nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
					SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
					memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
					memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
				}
				strcpy(obTranMapCurr.szMsgID, obTranMap[i].szMsgID);
				strcpy(obTranMapCurr.szProcCode, obTranMap[i].szProcCode);
				if (pobTran->inManual==1) {
					map_set(obTranMapCurr.bitmap, 2);
					map_set(obTranMapCurr.bitmap, 14);
					map_reset(obTranMapCurr.bitmap, 35);
				}
			} else if (pobTran->Status==1) { //Reversal
				strcpy((char *)obTranMapCurr.bitmap, (char *)obTranMap[i].bitmap_rev);
				{//SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, (char *)obTranMapCurr.bitmap, strlen((char *)obTranMapCurr.bitmap)/2); 
					memset(buff, 0x00, sizeof(buff));
					nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
					SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
					memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
					memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
				}
				strcpy(obTranMapCurr.szMsgID, obTranMap[i].szMsgID_rev);
				strcpy(obTranMapCurr.szProcCode, obTranMap[i].szProcCode_rev);
			} else if (pobTran->Status==2) { //Void
				strcpy((char *)obTranMapCurr.bitmap, (char *)obTranMap[i].bitmap_void);
				{//SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, (char *)obTranMapCurr.bitmap, strlen((char *)obTranMapCurr.bitmap)/2); 
					memset(buff, 0x00, sizeof(buff));
					nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
					SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
					memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
					memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
				}
				strcpy(obTranMapCurr.szMsgID, obTranMap[i].szMsgID_void);
				strcpy(obTranMapCurr.szProcCode, obTranMap[i].szProcCode_void);
				pobTran->VoidSTAN = pobTran->STAN + 15000;
			} else if (pobTran->Status==3) { //Reversal of Void
				strcpy((char *)obTranMapCurr.bitmap, (char *)obTranMap[i].bitmap_voidrev);
				{//SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, (char *)obTranMapCurr.bitmap, strlen((char *)obTranMapCurr.bitmap)/2); 
					memset(buff, 0x00, sizeof(buff));
					nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
					SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
					memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
					memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
				}
				strcpy(obTranMapCurr.szMsgID, obTranMap[i].szMsgID_voidrev);
				strcpy(obTranMapCurr.szProcCode, obTranMap[i].szProcCode_voidrev);
			} else if (pobTran->Status==2) { //advice, not used for now
				strcpy((char *)obTranMapCurr.bitmap, (char *)obTranMap[i].bitmap_advice);
				{//SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, (char *)obTranMapCurr.bitmap, strlen((char *)obTranMapCurr.bitmap)/2); 
					memset(buff, 0x00, sizeof(buff));
					nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
					SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
					memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
					memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
				}
				strcpy(obTranMapCurr.szMsgID, obTranMap[i].szMsgID_advice);
				strcpy(obTranMapCurr.szProcCode, obTranMap[i].szProcCode_advice);
			}
		}
	}

	if (strlen(obTranMapCurr.szMsgID)==0 || strlen(obTranMapCurr.szProcCode)==0){
		DisplayStatus("Bitmap Error");
		SVC_WAIT(1000);
		return 0;
	}
	//Customisasi Bitmap Start Here
/*
	if (pobTran->Status == 1) { //Reversal
		map_set(obTranMapCurr.bitmap, 2);
		map_set(obTranMapCurr.bitmap, 14);
		map_reset(obTranMapCurr.bitmap, 35);
		strcpy(obTranMapCurr.szMsgID, "0400");
	} else if (pobTran->Status == 2) { //void
		map_set(obTranMapCurr.bitmap, 2);
		map_set(obTranMapCurr.bitmap, 14);
		map_set(obTranMapCurr.bitmap, 37);
		map_reset(obTranMapCurr.bitmap, 35);
		obTranMapCurr.szProcCode[1] = '2';
		pobTran->VoidSTAN = pobTran->STAN + 15000;
	} else if (pobTran->Status == 3) { //reversal of void
		map_set(obTranMapCurr.bitmap, 2);
		map_set(obTranMapCurr.bitmap, 14);
		map_reset(obTranMapCurr.bitmap, 35);
		strcpy(obTranMapCurr.szMsgID, "0400");
	}
*/
	return 1;
}

int PackMessage(TRANSACTION_OBJECT *pobTran, unsigned char *SentBuff)
{
	int PacketSize;
	char buff[128];
	
	memset(source, 0x00, sizeof(source));
	memset(dest, 0x00, sizeof(dest));
/////////////////////

	memset(buff, 0x00, sizeof(buff));
	get_env_x(HOST_ID, 0, buff);
	buff[3]=0x00;
	if (strlen(buff) < 3) {
		pad (buff, buff, 0x30, 3, LEFT);
	}
	strcpy((char *)ISOMess.field_24, buff);
	sprintf((char *)ISOMess.tpdu, "600%s80EC", (char *)ISOMess.field_24);
	
	memset(buff, 0x00, sizeof(buff));
	get_env_x(HOST_TERMINAL, 0, buff);
	strcpy((char *)ISOMess.field_41, buff);

	memset(buff, 0x00, sizeof(buff));
	get_env_x(HOST_TERMINAL, 1, buff);
	strcpy((char *)ISOMess.field_42, buff);
	
	strcpy((char *)ISOMess.message_id, obTranMapCurr.szMsgID);				//ok
	strcpy((char *)ISOMess.field_02, pobTran->szPAN);					//ok

	strcpy((char *)ISOMess.field_03, obTranMapCurr.szProcCode);				//ok

	if (pobTran->inCode != PMT_TRX_INFO_BILLING && pobTran->inCode != PMT_TRX_INFO_NAME) {
		if (pobTran->inAccType == 3) { //current account for PERMATA
			ISOMess.field_03[2] = '2';
		}
	}

	//sprintf((char *)ISOMess.field_04, "%ld00", pobTran->Total);			//ok
	strncpy((char *)ISOMess.field_04, pobTran->szTotal, 12);

	if (pobTran->lnVoucherAmt > 0) {
		sprintf((char *)ISOMess.field_04, "%ld00", pobTran->lnVoucherAmt);
	}

	if (pobTran->Status == 2 || pobTran->Status==3) {
		sprintf((char *)ISOMess.field_11, "%06d", pobTran->VoidSTAN);			//ok
	} else {
		sprintf((char *)ISOMess.field_11, "%06d", pobTran->STAN);			//ok
	}
	strcpy ((char *)ISOMess.field_12, pobTran->szTime);					//ok
	strcpy ((char *)ISOMess.field_13, &pobTran->szDate[2]);				//ok
	strcpy ((char *)ISOMess.field_14, pobTran->szExpDate);				//ok
	//sprintf((char *)ISOMess.field_22, "%03d", pobTran->EntryMode);
	if (pobTran->inManual==1) {
       strcpy ((char *)ISOMess.field_22, MANUAL_POS_ENTRY_CODE);			//ok
	} else {
       strcpy ((char *)ISOMess.field_22, SWIPE_POS_ENTRY_CODE);			//ok
	}
	strcpy ((char *)ISOMess.field_25, "00");							//ok
	memcpy ((char *)ISOMess.field_35, pobTran->stT2Data, TRACK2_SIZE);  //ok
	strcpy ((char *)ISOMess.field_37, pobTran->szRetRefNum);			//ok for VOID
    strcpy ((char *)ISOMess.field_38, pobTran->szAuthCode);				//ok for Offline refund
    pad ((char *)ISOMess.field_38,(char *)ISOMess.field_38,0x20,AUTH_CODE_SIZE,LEFT); //powerfull function 0x20=SPACE
	//memcpy ((char *)ISOMess.field_39, pobTran->szRespCode, 2);			//ok
	//memcpy(srISO.pszField45, pobTran->srBRec.stT1Data, TRACK1_SIZE);	//ok
	
	if (pobTran->inCode == PMT_TRX_ISI_ULANG) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s%04d", 33, pobTran->szInputNumber_1, 0);
	} else if (pobTran->inCode == PMT_TRX_REGISTRASI) {
		sprintf((char *)ISOMess.field_48, "%04d%-16s", 0, pobTran->szInputNumber_1);
	} else if (pobTran->inCode == PMT_TRX_TIN  || pobTran->inCode == PMT_TRX_PIN_CHANGE) {
		strcpy((char *)ISOMess.field_48, "0000");
		strncat((char *)ISOMess.field_48, pobTran->szPIN2, 16);
	} else if (pobTran->inCode == PMT_TRX_INFO_CDTCARD) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s%-8s", 5, pobTran->szInputNumber_1, pobTran->szInputNumber_2);
	} else if (pobTran->inCode == PMT_TRX_BAYAR_CDTCARD) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 5, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_TELPON) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 1, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_PLN) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 2, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_PALYJA) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 26, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_PAM) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 45, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_ACC) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 41, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_FIF) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 44, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_TAF) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 12, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_ADIRA) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s", 11, pobTran->szInputNumber_1);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_SCB) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
	} else if (pobTran->inOriginalCode == PMT_TRX_CICILAN_CITI) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_PENDIDIKAN) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		if (atoi(pobTran->szAdditionalInfo)==0) {
			sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
		} else {
			sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(pobTran->szAdditionalInfo), pobTran->szInputNumber_1);
		}
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_ASURANSI) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_TIKET) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		if (atoi(pobTran->szAdditionalInfo)==0) {
			sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
		} else {
			sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(pobTran->szAdditionalInfo), pobTran->szInputNumber_1);
		}
	} else if (pobTran->inOriginalCode == PMT_TRX_BAYAR_PAYID) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_1, 3);
		sprintf((char *)ISOMess.field_48, "%04d%-18s", atoi(szInst), &pobTran->szInputNumber_1[3]);
	} else if (pobTran->inOriginalCode == PMT_TRX_TRANSFER) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s%-18s%-30s%-20s%06d", 0, 
			pobTran->szInputNumber_3, pobTran->szInputNumber_2, " ", " ", 13);
	} else if (pobTran->inOriginalCode == PMT_TRX_TRANSFER_REK_LAIN) {
		sprintf((char *)ISOMess.field_48, "%04d%-18s%-18s%-30s%-20s%06d", 0, 
			pobTran->szInputNumber_3, pobTran->szInputNumber_2, " ", " ", 13);
	} else if (pobTran->inOriginalCode == PMT_TRX_TRANSFER_BANK_LAIN) {
		char szInst[4];
		memset(szInst, 0x00, sizeof(szInst));
		strncpy(szInst, pobTran->szInputNumber_2, 3);
		if (atoi(pobTran->szAdditionalInfo)==0) {
			sprintf((char *)ISOMess.field_48, "%04d%-18s%-18s%-30s%-20s%06d", 0, 
				pobTran->szInputNumber_3, &pobTran->szInputNumber_2[3], " ", " ", atoi(szInst));
		} else {
			sprintf((char *)ISOMess.field_48, "%04d%-18s%-18s%-30s%-20s%06d", 0, 
				pobTran->szInputNumber_3, pobTran->szInputNumber_2, " ", " ", atoi(pobTran->szAdditionalInfo));
		}
	} else {
		//strcpy((char *)ISOMess.field_48, pobTran->szCVV2Value,CVV2_SIZE);	//ok
	}
	if (strlen(pobTran->szF48)) {
		strcpy((char *)ISOMess.field_48, pobTran->szF48);
	}
	
	//SVC_DSP_2_HEX(pobTran->szPIN, pobTran->szPIN, 8);  //asc to bcd move to GetEncPIN
	memcpy((char *)ISOMess.field_52, pobTran->szPIN, 8);				//ok
	//sprintf((char *)ISOMess.field_54, "%ld", pobTran->Tip);			//ok
	//strcpy((char *)ISOMess.field_60, "01206");
	//sprintf((char *)ISOMess.field_60, "%-20s%018ld00", pobTran->szRcptAcc, pobTran->Total); //BRI
	//sprintf((char *)ISOMess.field_60, "%-20s%-30s", pobTran->szRcptAcc, pobTran->szRcptName);
	sprintf((char *)ISOMess.field_62, "%06ld", pobTran->lnInvNum);
	strcpy((char *)ISOMess.field_63, "POSBRI");
	//SVC_DSP_2_HEX(pobTran->szRcptAcc, (char *)&ISOMess.field_63[4], 5);

//////////////////////
	LOG_PRINTFF((0x08L, "pobTran Track2 (%d) = %s", strlen(pobTran->stT2Data), pobTran->stT2Data));
    iso8583_main(convert_table, return_variant1, return_variant2, dest, source);  
	PacketSize = process_8583(0, field_table, obTranMapCurr.bitmap, &SentBuff[2], MSG_BUFF_SIZE-3);  //to pack
	if (PacketSize>0) {
		SentBuff[0] = PacketSize / 256;
		SentBuff[1] = PacketSize % 256;
	}
	LOG_PRINTFF((0x08L, "Packet Size = %d", PacketSize));
	return PacketSize;  //should return the PacketSize
}

int UnpackAndValidateMessage(TRANSACTION_OBJECT *pobTran, unsigned char *RecvBuff)
{
	int PacketSize;
	int i;
	char buff[128];
	long lnTmpTotal;

	memset(buff, 0x00, sizeof(buff));
	memset(source, 0x00, sizeof(source));
	memset(dest, 0x00, sizeof(dest));
	memset((char *)&ISOMess, 0x00, sizeof(ISOMess));

    PacketSize = process_8583(1, field_table, obTranMapCurr.bitmap, &RecvBuff[2], RecvBuff[0]*256 + RecvBuff[1]);  //to unpack, isomap will be ignored
////////////////////
//Checking Message Integrity
////////////////////
	LOG_PRINTFF((0x08L, "Unprocessed Recv Packet = %d", PacketSize));
	if (PacketSize < 0) { //Kelebihan packet allowed
		DisplayStatus("Invalid Msg Response!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return 0;
	}
/*	
	memset(buff, 0x00, sizeof(buff));
	strcpy(buff, (char *)ISOMess.message_id);
	LOG_PRINTFF((0x08, "MSG ID = [%s]", buff));
	buff[2] = buff[2] - 0x01;
	LOG_PRINTFF((0x08, "MSG ID = [%s]", buff));
	if (strcmp(buff, obTranMapCurr.szMsgID)) {
		DisplayStatus("Unexpected Msg");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return 0;
	}
*/
	if (pobTran->Status == 2 || pobTran->Status==3) {
	   if (pobTran->VoidSTAN != atol((char *)ISOMess.field_11)) {  //STAN Check
		  DisplayStatus("STAN Check Failed!");
		  vdWarnBeep();
		  SVC_WAIT(2000);		
		  LOG_PRINTFF((0x08L, "STAN %s ==> %ld", (char *)ISOMess.field_11, atol((char *)ISOMess.field_11)));
		  return 0;
	   }
	} else {
	   if (pobTran->STAN != atol((char *)ISOMess.field_11)) {  //STAN Check
		  DisplayStatus("STAN Check Failed!");
		  vdWarnBeep();
		  SVC_WAIT(2000);		
		  LOG_PRINTFF((0x08L, "STAN %s ==> %ld", (char *)ISOMess.field_11, atol((char *)ISOMess.field_11)));
		  return 0;
	   }
	}

	memset(buff, 0x00, sizeof(buff));
	get_env_x(HOST_TERMINAL, 0, buff);
	if (strlen((char *)ISOMess.field_41)) {
		if (strcmp(buff, (char *)ISOMess.field_41)){
		  DisplayStatus("TID Check Failed!");
		  vdWarnBeep();
		  SVC_WAIT(2000);		
		  return 0;
		}
	} else {
		DisplayStatus("No TID Field!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return 0;
	}
/////////////////////
//Response Code Check
/////////////////////
	if (strlen((char *)ISOMess.field_39)==2) {
		strcpy(pobTran->szRespCode, (char *)ISOMess.field_39);
	} else {
		DisplayStatus("Approval Code Failed!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return 0;
	}

	if ((char)RecvBuff[2+7] & (char)0x10) { //Checking the existance of bit 4)
	   if (strlen((char *)ISOMess.field_04)>=2) {
		  //pobTran->Total = strtol((char *)ISOMess.field_04, NULL, 10);
		  memset(pobTran->szTotal, 0x00, sizeof(pobTran->szTotal));	
		  strcpy(pobTran->szTotal, (char *)ISOMess.field_04);
		  ISOMess.field_04[strlen((char *)ISOMess.field_04)-2] = 0x00;
		  lnTmpTotal = atol((char *)ISOMess.field_04);
		  LOG_PRINTFF((0x08L, "%s ==> %ld", (char *)ISOMess.field_04, lnTmpTotal));
	   } else {
		  lnTmpTotal = 0;
	   }
	   pobTran->Total = lnTmpTotal;
	}

	if (strlen((char *)ISOMess.field_12))
		strcpy(pobTran->szTime, (char *)ISOMess.field_12);

	if (strlen((char *)ISOMess.field_13))
		strcpy(&pobTran->szDate[2], (char *)ISOMess.field_13);

	if (strlen((char *)ISOMess.field_37))
		strcpy(pobTran->szRetRefNum, (char *)ISOMess.field_37);

	if (strlen((char *)ISOMess.field_38))
		strcpy(pobTran->szAuthCode, (char *)ISOMess.field_38);

	if (strlen((char *)ISOMess.field_48)) {
		if ((pobTran->inCode == PMT_TRX_ISI_ULANG) && (strlen((char *)ISOMess.field_48)>12)) {
			strcpy(pobTran->szVoucherSN, (char *)&ISOMess.field_48[strlen((char *)ISOMess.field_48)-12]);
		}
		LOG_PRINTFF((0x08L, "F48 = [%s] %d", (char *)ISOMess.field_48, strlen((char *)ISOMess.field_48)));
		LOG_PRINTFF((0x08L, "Max Size of F48 = [%d]", sizeof(pobTran->szF48)));
		memset(pobTran->szF48, 0x00, sizeof(pobTran->szF48));
		strncpy(pobTran->szF48, (char *)ISOMess.field_48, sizeof(pobTran->szF48)-1);
	}

	if ((char)RecvBuff[2+13] & (char)0x04) { //Checking the existance of bit 54)
		if (strlen((char *)ISOMess.field_54)) {
			LOG_PRINTFF((0x08L, "F54 = [%s] %d", (char *)ISOMess.field_54, strlen((char *)ISOMess.field_54)));
			LOG_PRINTFF((0x08L, "Max Size of F54 = [%d]", sizeof(pobTran->szF54)));
			memset(pobTran->szF54, 0x00, sizeof(pobTran->szF54));
			strncpy(pobTran->szF54, (char *)ISOMess.field_54, sizeof(pobTran->szF54)-1);
		}
	}

	if ((strlen((char *)ISOMess.field_63)) && (!strcmp(pobTran->szRespCode, "00"))) {
		LOG_PRINTFF((0x08L, "F63 = [%s] %d", (char *)ISOMess.field_63, strlen((char *)ISOMess.field_63)));
		LOG_PRINTFF((0x08L, "Max Size of F63 = [%d]", sizeof(pobTran->szF63)));
		memset(pobTran->szF63, 0x00, sizeof(pobTran->szF63));
		strncpy(pobTran->szF63, (char *)ISOMess.field_63, sizeof(pobTran->szF63)-1);
	}

///////////////////
	//inDisplayHostResponse(pobTran);
	return 1;
}

int inDisplayHostResponse(TRANSACTION_OBJECT *pobTran)
{
	char buff[42];
	char buff1[42];
	char buff2[42];

	memset(buff, 0x00, sizeof(buff));
	if (strlen((char *)ISOMess.field_63)>40) {
		strncpy(buff, (char *)ISOMess.field_63, 40);
	} else if (strlen((char *)ISOMess.field_63)){
		strcpy(buff, (char *)ISOMess.field_63);
	} else if (!strcmp(pobTran->szRespCode, "00")) {
		sprintf(buff, "Approved - %s", pobTran->szRespCode);
	} else if (!strcmp(pobTran->szRespCode, "02")) {
		sprintf(buff, "Declined - %s", pobTran->szRespCode);
	} else {
		sprintf(buff, "System Error - %s", pobTran->szRespCode);
	}

	if (strcmp(pobTran->szRespCode, "00")) vdWarnBeep();

	memset(buff1, 0x00, sizeof(buff1));
	memset(buff2, 0x00, sizeof(buff2));
	if (strlen(buff) > 20) {
		strncpy(buff1, buff, 20);
		strcpy(buff2, &buff[20]);
	} else {
		strcpy(buff1, buff);
	}
	vdTrimSpace(buff1);
	vdTrimSpace(buff2);
	LOG_PRINTFF((0x08L, "BIT63 = [%s]", buff));
	LOG_PRINTFF((0x08L, "Line1 = [%s]", buff1));
	LOG_PRINTFF((0x08L, "Line2 = [%s]", buff2));
	
	vdFormatText(buff1, 21, CENTERED);
	DisplayStatus(buff1);
	if (strlen(buff2)){
		if (pobTran->inCode==PMT_TRX_PURCHASE) vdDisplayMerchantName();
		vdScrollDisplay();
		vdFormatText(buff2, 21, CENTERED);
		DisplayStatus(buff2);
	}
	if (strcmp(pobTran->szRespCode, "00")) {
		//SVC_WAIT(3000);
		pause(6000);
		return 0;
	}
	SVC_WAIT(0);
	return 1;
}